﻿using System;
using System.Threading;
using System.Windows.Input;
using Chambills.Present.Core.NotifyOnChange;
using Present.Commands.Fluent;
using Present.Commands.Async.Actions;

namespace Present.Commands.Sample.MainDemo
{
    public class SampleCommands : NotifiableObject, IBusyable
    {
        private bool isBusy;
        private readonly Random random =  new Random((int)DateTime.Now.Ticks);


        public SampleCommands()
        {
            ScheduledCommand = CreateScheduledCommand();
            BusyCommand = CreateBusyCommand();
            CompositeCommand = CreateCompositeCommand();
        }


        public ICommand ScheduledCommand { get; private set; }
        public ICommand BusyCommand { get; private set; }
        public ICommand CompositeCommand { get; private set; }


        private static ICommand CreateScheduledCommand()
        {
            return Command
                    .FromDelegates()
                        .Execute(x =>
                                     {
                                         Logger.Instance.Log("Executing Scheduled Command");
                                         Logger.Instance.Log("Scheduled Command Finished");
                                     })
                    .ToCommand()
                    .Schedule()
                        .Every(TimeSpan.FromSeconds(5))
                    .ToCommand();
        }


        private ICommand CreateBusyCommand()
        {
            return Command.Async
                        (
                            AsyncAction.FromDelegates()
                                    .Do(x => Logger.Instance.Log("Executing Busy Command"))
                                    .OnSuccess(x => Logger.Instance.Log("Busy Command Finished"))
                                .Sleep(TimeSpan.FromSeconds(3))
                                .ShowBusy(this)
                                .ToAction()
                        )
                        .ToCommand();
        }

        private ICommand CreateCompositeCommand()
        {
            return Command.Async
                        (
                            AsyncAction.Multiple()
                            .Add(AsyncAction.FromDelegates()
                                                .Do(x => DoSomething("Executing Composite Command 1"))
                                                .OnSuccess(x => Logger.Instance.Log("Composite Command 1 Finished"))
                                            .ToAction()
                                            .ToObservable())
                            .Add(AsyncAction.FromDelegates()
                                                .Do(x => DoSomething("Executing Composite Command 2"))
                                                .OnSuccess(x => Logger.Instance.Log("Composite Command 2 Finished"))
                                            .ToAction()
                                            .ToObservable())
                            .WhenAllFinished(x => Logger.Instance.Log("Composite Command Finished"))
                            .ToAction()
                        )
                        .ToCommand();
        }


        private void DoSomething(string msg)
        {
            int sleep = random.Next(500, 2000);
            Logger.Instance.Log(msg + " for " + sleep);
            Thread.Sleep(sleep);
        }

        /// <summary>
        /// In real situations I implement this as a counter, true increments, false decrements and get returns the count == 0.
        /// </summary>
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                OnPropertyChanged(() => IsBusy);
            }
        }

    }
}
